package bat.ke.qq.com.threadpool;

import bat.ke.qq.com.MonkeyRejectedExecutionHandler;

import java.util.concurrent.*;

public class ThreadPoolDemo {
    public static void main(String[] args) {
        /**
         * 相当于有有n个项目，就找N个程序员做，但是有OOM得风险
         * 快:查看源码可知newCachedThreadPool
         *
         *  核心线程大小-corePoolSize：核心线程数为0
         *  最大线程数-maximumPoolSize:MAX_VALUE = 0x7fffffff
         *  非核心线程数：maximumPoolSize-corePoolSize
         *  SynchronousQueue：同步队列，未设置队列长度
         */
        ExecutorService executorService1 = Executors.newCachedThreadPool();
        /**
         *  相当于有10个程序员做N
         *  慢:查看源码newFixedThreadPool
         *  new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
         *  corePoolSize：核心线程数为10
         *  maximumPoolSize：最大线程数10 ，所以没有非核心线程数
         *  new LinkedBlockingQueue<Runnable>()：链式阻塞队列（先进先出）
         */
        ExecutorService executorService2 = Executors.newFixedThreadPool(10);

        /**
         * 相当于公司只有一个程序员在做项目N个项目
         *最慢：查看源码 newSingleThreadExecutor
         * new FinalizableDelegatedExecutorService
         *             (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()))
         * 核心线程数：1
         * 最大线程数：1
         * 链式阻塞队列：new LinkedBlockingQueue<Runnable>() 链式阻塞队列（先进先出）
         */
        ExecutorService executorService3 = Executors.newSingleThreadExecutor();

        RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                // 写数据库的代码
            }
        };

        /**
         * 自定义线程
         * corePoolSize：核心线程数
         * maximumPoolSize：最大线程数
         * 链式阻塞队列：new LinkedBlockingQueue<Runnable>() 链式阻塞队列长度10（先进先出）
         * MonkeyRejectedExecutionHandler: 自定义拒绝策略
         * 四种拒绝策略：不重要
         * （1）AbortPolicy
         * AbortPolicy
         * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
         * （2）DiscardPolicy
         * ThreadPoolExecutor.DiscardPolicy：丢弃任务，但是不抛出异常。如果线程队列已满，则后续提交的任务都会被丢弃，且是静默丢弃。
         * （3）DiscardOldestPolicy
         * ThreadPoolExecutor.DiscardOldestPolicy：丢弃队列最前面的任务，然后重新提交被拒绝的任务。
         * （4）CallerRunsPolicy
         * ThreadPoolExecutor.CallerRunsPolicy：由调用线程处理该任务
         */
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20,
                0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(10), new MonkeyRejectedExecutionHandler());
        for (int i = 1; i <= 100; i++) {
            threadPoolExecutor.execute(new MyTask(i));
        }
    }
}

/***
 * 项目
 */
class MyTask implements Runnable {
    int i = 0;

    public MyTask(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "程序员做第" + i + "个项目");
        try {
            //业务逻辑
            Thread.sleep(3000L);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
